/**
 * Joystick.h
 * Description: Joystick header file.
 * Authors: Hamish Cumming, Brian Thorne 2008
 *
 * The joystick comprises 5 pull up switches: PB4,6,7,PE2,3
 */

#include "joystick.h"
#include "ui.h"
#include "kernel.h"

/* File Variables */
static uint8_t states = 0;      // This records the state of the buttons: down,up,push,right,left corrospond to 16,8,4,2,1 etc...
static time_t pressed_at = {0};
static time_t action_at = {0};

/** Initialise the joystick */
uint8_t joystick_init(void)
{
    //Set pins as input
    DDRB &= ~PORTB_MASK;  // Port B
    DDRE &= ~PORTE_MASK;  // Port E

    // Pull up resistor must be enabled
    PORTB |= PORTB_MASK; // Port B
    PORTE |= PORTE_MASK; // Port E

    register_task(joystick_proccess, JOYSTICK_TASK);
    activate_task(JOYSTICK_TASK);

    return EXIT_SUCCESS;
}

/** The joystick task */
uint8_t joystick_proccess()
{
    time_t now = get_clock_value();
    uint32_t now32 = now.time32;

    uint8_t but = joystick_read();
    if(but && (now.time32 - action_at.time32 >= TIME_ACT )) // Only do stuff if a button is down and enough time has passed since last action.
    {
        if(!states)
        {
            //Save state and time
            pressed_at = get_clock_value();
            states = but;
        } else {
            uint32_t pressed_at32 = pressed_at.time32;
            // Need to check if enough time has passed.
            // If it has do the action. and save that time.
            if(but == states && now32 - pressed_at32>=TIME_BUT)
            {
                ui_move(but2dir(but));
                states = 0;
                action_at = get_clock_value();
            } else
            {
                states = 0;
            }
        }



    }
    return EXIT_SUCCESS;
}

/** A function that reads the 5 switches */
uint8_t joystick_read()
{
    uint8_t buttons =  (~PINB & PORTB_MASK) | (~PINE & PORTE_MASK);

    if (buttons)
    {
        // Joystick - Button Debouncing
        int16_t i = JOY_DEBOUNCE;
        for(;i>=0;i--);;
    }
    if(buttons == ((~PINB & PORTB_MASK) | (~PINE & PORTE_MASK)))
        return buttons;
    return 0;
}

/** Convert a button code (eg. JOY_LEFT) into a direction. */
direction_t but2dir(uint8_t con)
{
    //NOTE Will need optimising!
    static const uint8_t arr_pins[] = {1<<7,1<<6,1<<4,8,4};
    static const direction_t arr_dirs[] = {down,up,push,right,left};
    uint8_t i;
    for(i=0;i<5;i++)
    {
        if(con==arr_pins[i]) return arr_dirs[i];
    }
    return EXIT_FAIL;
}
